package com.sky.service.impl;

import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.mapper.*;
import com.sky.service.OrderService;
import com.sky.vo.OrderSubmitVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private ShoppingCartMapper shoppingCartMapper;

    @Autowired
    private AddressBookMapper addressBookMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    /**
     * 用户提交订单
     *  1. 订单数据包含订单本身的基本数据和订单的详情数据【买了什么具体的东西】
     *  2. 它们是存储在不同的表里面
     *         订单的基本数据放置在 订单表 orders
     *         订单详情 放置在 订单详情表 order_detail
     *  3. 需要往这两张表添加数据
     *      3.1 先添加订单表 ， 获取到ID，再每一个订单详情里面设置它。
     *      3.2 再添加订单详情表
     *
     * @param dto
     * @return
     */
    @Override
    public OrderSubmitVO add(OrdersSubmitDTO dto) {
        //1. 往订单表添加数据

        //1.0 转化数据模型
        Orders orders = new Orders();
        BeanUtils.copyProperties(dto ,orders);

        //1.1 准备数据
        //1.1.1 准备用户数据
        User user = userMapper.findById(BaseContext.getCurrentId());

        //1.1.2 准备地址数据
        AddressBook addressBook = addressBookMapper.getById(dto.getAddressBookId());

        //如果地址为空，则抛出异常！
        if(addressBook == null){
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }

        //1.2 补充数据
        fillOrders(orders , addressBook , user);

        //1.3 添加到订单表里面。
        orderMapper.add(orders);


        //2. 往订单详情表添加数据

        //2.1 先获取当前这个用户的购物车数据
        ShoppingCart cart = new ShoppingCart();
        cart.setUserId(BaseContext.getCurrentId());
        List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(cart);

        //2.2 要往订单详情表【order_detail】存数据, 表有对应的实体类： OrderDetail, 所以我们需要把购物车转化成OrderDetail
        // 有多少个购物车对象就要转化出来多少给OrderDetail对象
        List<OrderDetail> orderDetailList = shoppingCartList.stream().map(shoppingCart -> {

            //2.2.1 遍历一次，构建一个新的OrderDetail对象
            OrderDetail od = new OrderDetail();

            //2.2.2 搬运数据
            BeanUtils.copyProperties(shoppingCart, od);

            //2.2.3 设置订单详情属于哪一个订单
            od.setOrderId(orders.getId());

            return od;
        }).collect(Collectors.toList());

        //2.3. 往订单详情表添加数据。
        orderDetailMapper.addAll(orderDetailList);


        //3. 清空购物车
        shoppingCartMapper.deleteByUid(BaseContext.getCurrentId());


        //4. 组建返回的结果：
        return OrderSubmitVO.builder()
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .orderAmount(orders.getAmount())
                .orderTime(orders.getOrderTime())
                .build();


        /*List<OrderDetail> orderDetailList = new ArrayList<>();
        for (ShoppingCart shoppingCart : shoppingCartList) {

            //2.2.1 遍历一次，就创建一个OrderDetail 对象
            OrderDetail od = new OrderDetail();

            //2.2.2 把购物车数据搬运到od 对象
            BeanUtils.copyProperties(shoppingCart ,od);

            //2.2.3 设置属于哪一个订单
            od.setOrderId(orders.getId());


            // 2.2.4 一边添加到订单详情表 【一个一个的添加...】
            //orderDetailMapper.add(od);

            //TODO:: 打包到一个集合去，一会批量添加。
            orderDetailList.add(od);
        }

        //TODO:: 在这里批量添加
        //orderDetailMapper.addAll(orderDetailList);*/
    }

    /**
     * 填充订单数据
     * @param orders
     * @param addressBook
     * @param user
     */
    private void fillOrders(Orders orders , AddressBook addressBook , User user){
        //1.2.1 设置id :: 自增ID，不用设置
        //1.2.2 设置number 订单号（时间+地区城市+编号...） UUID
        orders.setNumber(UUID.randomUUID().toString().replace("-",""));
        //订单的状态：1: 待付款
        orders.setStatus(Orders.PENDING_PAYMENT);
        //1.2.3 设置user_id 用户ID
        orders.setUserId(BaseContext.getCurrentId());
        //1.2.4 设置address_book_id:: 页面有提供不用设置！
        //1.2.5 设置order_time:: 下单时间
        orders.setOrderTime(LocalDateTime.now());
        //1.2.6 设置checkout_time:: 付款时间，不知道，后续更新它
        //1.2.7 设置pay_method:: 支付方式，下单才知道。后续要更新它
        //1.2.8 设置pay_status:: 支付状态： 0 未支付， 1已支付， 2退款
        orders.setPayStatus(Orders.UN_PAID);
        //1.2.9 设置amount:: 订单总金额，页面提供
        //1.2.10 设置remark:: 备注，前端提供
        //1.2.11 设置phone::  收货人电话，需要设置
        orders.setPhone(addressBook.getPhone());
        //1.2.12 设置address :: 收货人地址，需要设置
        String address = addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail();
        orders.setAddress(address);
        //1.2.13 设置user_name :: 下单的这个用户的昵称
        orders.setUserName(user.getName());
        //1.2.14 设置consignee :: 收货人姓名
        orders.setConsignee(addressBook.getConsignee());
        //1.2.15 设置cancel_reason :: 取消订单的原因，后续更新它
        //1.2.16 设置rejection_reason:: 拒绝订单的原因， 后续更新它
        //1.2.17 设置estimatedDeliveryTime :: 页面提供，不用设置
        //1.2.18 设置delivery_status:: 配送状态 页面提供，不用设置
        //1.2.18 设置delivery_time:: 送达时间，后续需要更新它
        //1.2.19 设置pack_amount :: 打包费，页面提供不用设置
        //1.2.20 设置tablewareNumber:: 餐具数量，页面提供，不用设置
        //1.2.21 设置tablewareStatus :: 餐具数量状态，页面提供，不用设置
    }
}
